#include "sharedmemory.h"
#include <malloc.h>
#include <stdlib.h>



Queue getBlockQueueMem(const int max_num_processes);

Memory newMemory(CPU_MEM cpu, int max_processes) {
	Memory memory = (Memory) malloc(sizeof(MemoryStr));
	memory->cpu = cpu;
	memory->semaphore = DEFAULT_MIN_VALUE;
	memory->max = DEFAULT_MAX_VALUE;
	memory->min = DEFAULT_MIN_VALUE;
	memory->block_queue = getBlockQueueMem(max_processes);

	return memory;
}

Queue getBlockQueueMem(const int max_num_processes) {
	Queue block_queue = createQueue(max_num_processes);
	return block_queue;
}

void incrementMemory(Memory memory, Process p) {
	if (memory->semaphore == memory->max) {
		p->pcb->state = BLOCKED;
		enqueue(p, memory->block_queue);
	} else {
		pthread_mutex_lock(&(memory->mutex_semaphore));
		memory->semaphore = memory->semaphore + 1;
		pthread_mutex_unlock (&(memory->mutex_semaphore));
		if (!isEmpty(memory->block_queue) &&
				((Process) front(memory->block_queue))->process_type == CONSUMER) {
			memoryInterruptHandler(memory->cpu, frontAndDequeue(memory->block_queue));
		}
	}
	return;
}

void decrementMemory(Memory memory, Process p) {
	if (memory->semaphore == memory->min) {
		p->pcb->state = BLOCKED;
		enqueue(p, memory->block_queue);
	} else {
		pthread_mutex_lock(&(memory->mutex_semaphore));
		memory->semaphore = memory->semaphore - 1;
		pthread_mutex_unlock (&(memory->mutex_semaphore));
		if (!isEmpty(memory->block_queue) &&
				((Process) front(memory->block_queue))->process_type == PRODUCER) {
			memoryInterruptHandler(memory->cpu, frontAndDequeue(memory->block_queue));
		}
	}
	return;
}
